const rewire = require('rewire')
const R = require('ramda')
const cheerio = require('cheerio')
const webdriver = rewire('../common/selenium.cjs')
const utils = rewire('../common/utils.cjs')
const dbutils = rewire('../common/dbutils.cjs')
const combinator = rewire('../common/combinator.cjs')
const state = rewire('../state.cjs')
const proxyClient = rewire('../common/proxy.cjs')

async function main() {
  const client = await initDriver()
  await doCountryTask(client)
  await doAllProvinceTask(client)
}


async function doCountryTask(client) {
  const keys = ['国械注准', '国械注进', '国械备', '国械注许']
  for (let key of keys) {
    await doKeywordTask(client, key)
  }
  await doKeywordTask(client, '国械注准', guozhuType)
  await doKeywordTask(client, '国械注进', jinzhuType)
  await doKeywordTask(client, '国械备', guobeiType)
  await doKeywordTask(client, '国械注许', jinzhuType)
}


async function doKeywordTask(client, key, guozhuType) {
  const resp = await searchFirstPage(client, key, guozhuType)
  if (resp < 9990) {
    await doFetchAllData(client, key)
  }
  else {
    const years = R.range(2008, 2023)
    const keywords = R.map(y => key + year, years)
    for (let k of keywords) {
      const count = await searchFirstPage(client, k, guozhuType)
      if (count == 9990) {
        console.error(key + ': 数量超出')
      }
      await doFetchAllData(client, k)
    }
  }
}

async function doAllProvinceTask(client) {
  const allProvinces = data.getProvinceList()
  for (let provinceInfo of allProvinces) {
    await doProvinceTask(client, provinceInfo)
  }
}

async function doProvinceTask(client, provinceInfo) {
  const cityShorts = data.getCityShortList(provinceInfo)
  const pshort = data.provinceShort(provinceInfo[1])
  await doKeywordTask(client, pshort + '械注准', guozhuType)
  await doKeywordTask(client, pshort + '械备', guobeiType)
  for (let city of cityShorts) {
    await doKeywordTask(client, city + '械备', guobeiType)
  }
}


async function initDriver(client) {
  await webdriver.driverGoto(client, 'https://www.nmpa.gov.cn/datasearch/home-index.html#category=ylqx')
  const skipBtn1 = await webdriver.elemFindItem(client, '.introjs-skipbutton')
  await webdriver.elemClick(skipBtn1)
  const elem = await webdriver.elemFindItem(client, '.search-input .el-input__inner')
  await webdriver.elemInput(elem, '国械')
  await webdriver.driverWaitTime(client, 1000)
  const btn = await webdriver.elemFindItem(client, '.search-input .el-input-group__append button')
  await webdriver.elemClick(btn)

  await webdriver.switchTab(client, 2)
  const skipBtn2 = await webdriver.elemFindItem(client, '.introjs-skipbutton')
  await webdriver.elemClick(skipBtn2)
  await webdriver.closeTab(client, 1)

  await webdriver.cssClick(client, '.el-pagination .el-select .el-input .el-input__inner')
  const els = await webdriver.elemFindList(client, '.el-select-dropdown__item')
  await webdriver.elemClick(els[1])
  await webdriver.driverClick(client, 100, 500)
  return client
}


async function clearCheckElem(client) {
  const exist = await webdriver.elemExists(client, '.el-cascader__tags .el-tag .el-icon-close')
  if (exist) {
    await webdriver.cssClick(client, '.el-cascader__tags .el-tag .el-icon-close')
  }
}

const guozhuType = 0
const guobeiType = 2
const jinzhuType = 3
const jinbeiType = 5

async function searchFirstPage(client, key, type) {
  await clearCheckElem(client)
  // 选择分类
  await webdriver.cssClick(client, '.el-cascader .el-input')
  await webdriver.driverWaitTime(client, 1000)
  let casParents = await webdriver.elemFindList(client, '.el-cascader-panel .el-cascader-menu')
  const onePanel = casParents[0]
  const lielm1 =await webdriver.elemGetChildrenList(onePanel, 'li.el-cascader-node')
  await webdriver.elemClick(lielm1[1])
  await webdriver.driverWaitTime(client, 1000)

  casParents = await webdriver.elemFindList(client, '.el-cascader-panel .el-cascader-menu')
  const twoPanel = casParents[1]
  const lielm2 = await webdriver.elemGetChildrenList(twoPanel, 'li.el-cascader-node')
  await webdriver.elemClick(lielm2[type])
  await webdriver.driverClick(client, 100, 500)

  // 搜索关键词
  const inputElem = await webdriver.elemFindItem(client, '.el-input-group--append .el-input__inner')
  await inputElem.clear()
  await webdriver.elemInput(inputElem, key)
  await webdriver.cssClick(client, '.search-input .el-icon-search')
  await webdriver.driverWaitTime(client, 2000)

  //提取数据
  const totalText = await webdriver.cssGetText(client, '.el-pagination__total')
  const total = utils.extractNum(totalText)
  console.log(total)
  return total
}


async function countExecuteTime(afn, msg = '总共花费') {
  const timeStart = utils.currentMs()
  const rs = await afn()
  const timeEnd = utils.currentMs()
  console.log(msg + '：' + (timeEnd - timeStart))
  return rs
}

async function parseDetailInfo(client) {
  await webdriver.driverWaitUtil(client, async function(driver) {
    return (await webdriver.cssGetText(client, '.el-table_1_column_2')).trim() != ''
  })

  const html = await webdriver.getHtml(client)
  const $ = cheerio.load(html)
  const elemLefts = $('.el-table_1_column_1')
  const elemRights = $('.el-table_1_column_2')

  const rs = []
  for (let i = 0; i < elemLefts.get().length; i++) {
    const elemLeft = elemLefts.eq(i)
    const elemRight = elemRights.eq(i)
    const name = elemLeft.text()
    const value = elemRight.text()
    rs.push(R.pair(name.trim(), value.trim()))
  }

  console.log(rs)
  return rs
}

const parseDetailInfoRetry = combinator.errorRetry(parseDetailInfo, 3)


async function doFetchAllData(client, key) {
  async function doTask(page) {
    await doFetchPageData(client, page, key)

    const nextBtn = await webdriver.elemFindItem(client, '.btn-next')
    const isValid = !(await webdriver.elemHasAttr(nextBtn, 'disabled', 'disabled'))
    if (isValid) {
      await webdriver.elemClick(nextBtn)
      await webdriver.driverWaitUtil(client, async function(driver) {
        const pageInput = await webdriver.elemFindItem(client, '.el-pagination__jump input')
        const cpage = await webdriver.elemGetValue(pageInput)
        return (cpage + '') == ((page + 1) + '')
      }, '加载详情页数据失败')
      await doTask(page + 1)
    }
  }
  const lastpage = await getFetchLastPage(key)
  await gotoThisPage(client, lastpage + 1)
  await doTask(lastpage + 1)
}

async function gotoThisPage(client, page) {
  const input = await webdriver.elemFindItem(client, '.el-pagination__jump input')
  await webdriver.elemInputSet(input, page)
  await webdriver.sendEnter(client, input)
}



async function doFetchPageData(client, page, key) {
  const rowDoms = await webdriver.elemFindList(client, '.el-table__body .el-table__row')
  for (let row of rowDoms) {
    const btn = await webdriver.elemGetChildrenItem(row, 'button.el-button--primary')
    await webdriver.elemClick(btn)
    await webdriver.switchTab(client, 1)
  }
  const result = []
  for (let i = 0; i < rowDoms.length; i++) {
    await webdriver.switchTab(client, 20 - i + 1)
    const rowDetail = await parseDetailInfoRetry(client)
    const data = R.fromPairs(rowDetail)
    const info = {regist_num: data['注册证编号'], company: data['注册人名称'], product_name: data['产品名称'], datapack: JSON.stringify(data)}
    result.push(info)
  }

  await webdriver.switchTab(client, 1)
  for (let i = 0; i < rowDoms.length; i++) {
    await webdriver.closeTab(client, 2)
  }

  await savePageData(key, page, result)
  return
}

async function savePageData(key, page, result) {
  await dbutils.insertAll(
    state.getDb(), 'nmpa_keyword_history',
    [{keyword: key, page: page}]
  )
  await dbutils.insertAllNotIn(
    state.getDb(), 'nmpa',
    'regist_num',
    result
  )
}

async function getFetchLastPage(key) {
  const info =  await state.getDb()
    .select('*')
    .from('nmpa_keyword_history')
    .where('keyword', key)
    .orderby('id desc')
    .queryRow()
  if (info) {
    return info.page
  }
  else {
    return 0
  }
}


async function createWebDriverFirfoxProxy(name) {
  const proxy = await proxyClient.getRamdomProxy()
  return await webdriver.createWebDriverFirfox(name, true, proxy)
}

let client = null

async function mainTest() {
  client = await createWebDriverFirfoxProxy('nmpa', true)
  await initDriver(client)
  await searchFirstPage(client, '粤械', guozhuType)
  //await doFetchPageData(client, 1, '粤械')
  await doFetchAllData(client, '粤械')
}

const test = combinator.errorRetry(mainTest, 3, async function() {
  await client.quit()
})


test()



client = await createWebDriverFirfoxProxy('qqq')
